<?php

namespace App\Models;

use App\Http\Config\WechatAPI;
use App\Library\Tools;
use App\Models\Admin\Configs;
use App\Models\Admin\Withdrawal;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Log;

class Wechat extends Model
{
    static $object;

    /**
     * @return Wechat
     */
    public static function getInstance(){
        if(empty(self::$object)){
            self::$object = new self();
        }
        return self::$object;
    }

    public function Conf($select = "*")
    {
        $res = Configs::query()->select($select)->where("mall_id", request()->mallData['id'])->first();
        if(!empty($res)){
            return $res->toArray();
        }else{
            throw new \Exception("未配置系统");
        }
    }

    public function getToken($type = 'qywx')
    {
        $config = $this->Conf(["company_id", 'tongxl_secret']);
        $access_token = Cache::get($type.'_access_token_'.$config['company_id']);
        if(!empty($access_token)){
            return $access_token;
        }
        if($type=='wechat'){
            $url = '';
        }elseif ($type=='qywx'){
            $url = WechatAPI::$qywx_conf['get_token'].'?corpid='.$config['company_id'].'&corpsecret='.$config['tongxl_secret'];
        }else{
            $url = '';
        }
        $get_token_res = json_decode(file_get_contents($url), true);
        if(empty($get_token_res['access_token'])){
            throw new \Exception(isset(WechatAPI::$qyWx_msg[$get_token_res['errcode']]) ? WechatAPI::$qyWx_msg[$get_token_res['errcode']] : $get_token_res['errmsg']);
        }
        Cache::put($type.'_access_token_'.$config['company_id'], $get_token_res['access_token'], $get_token_res['expires_in'] / 60);
        return $get_token_res['access_token'];
    }

    /* 部门列表 */
    public function departmentList($departmentId = 0){
        $access_token = $this->getToken('qywx');
        $url = WechatAPI::$qywx_conf['department_list'].'?access_token='.$access_token;
        if($departmentId){
            $url .= "&id={$departmentId}";
        }
        $data = @json_decode(file_get_contents($url), true);
        return !empty($data['department']) ? $data['department'] : [];
    }

    /* 邀请企业用户 */
    public function inviteQYUser($fields)
    {
        $access_token = $this->getToken('qywx');
        $url = WechatAPI::$qywx_conf['user_invite'].'?access_token='.$access_token;
        $data = json_encode($fields,JSON_UNESCAPED_UNICODE);
        $result = Tools::curl($url, $data);
        return json_decode($result,true);
    }

    /* 企业账号 [获取/增加/修改/删除/批量删除] */
    public function buildQYUserWechat($fields, $action)
    {
        $access_token = $this->getToken('qywx');
        if($action == 'create'){
            $url = WechatAPI::$qywx_conf['user_create'].'?access_token='.$access_token;
        }elseif ($action == 'update'){
            $url = WechatAPI::$qywx_conf['user_update'].'?access_token='.$access_token;
        }elseif ($action == 'delete'){
            $url = WechatAPI::$qywx_conf['user_delete'].'?access_token='.$access_token.'&userid='.$fields['userid'];
            $result = file_get_contents($url);
            return json_decode($result,true);
        }elseif ($action == 'batch_delete'){
            $url = WechatAPI::$qywx_conf['user_batch_delete'].'?access_token='.$access_token;
        }elseif ($action == 'get'){
            $url = WechatAPI::$qywx_conf['user_get'].'?access_token='.$access_token.'&userid='.$fields['userid'];
        }elseif ($action == 'branch_user'){
            $url = WechatAPI::$qywx_conf['branch_user'].'?access_token='.$access_token;
        }elseif ($action == 'branch_user_detail'){
            $url = WechatAPI::$qywx_conf['branch_user_detail'].'?access_token='.$access_token;
        }elseif ($action == 'user_openid'){
            $url = WechatAPI::$qywx_conf['user_openid'].'?access_token='.$access_token;
        }
        $data = json_encode($fields,JSON_UNESCAPED_UNICODE);
        $result = Tools::curl($url, $data);
        return json_decode($result,true);
    }

    /* 企业微信转账 */
    public function payment($data)
    {
        global $scf_data;
        try {
            $config = $this->Conf();
            $arr = array(
                'amount' => $data['bonus_money'] * 100,
                'appid' => $config['company_id'],
                'desc' => '售后提成',
                'mch_id' => $config['qy_mch_id'],
                'nonce_str' => Tools::createNoncestr(),
                'openid' => $data['openid'],
                'partner_trade_no' => $data['order_number'],
                'ww_msg_type' => 'NORMAL_MSG'
            );
            $arr['workwx_sign'] = $this->makeSign($arr, ['column' => 'secret', 'value' => $config['qy_pay_secret']]);  //企业支付secret
            $arr['check_name'] = 'NO_CHECK';
            if (!empty($scf_data)) {
                $certAddress = "/tmp/apivlient_cert_crm.pem";
                $keyAddress = "/tmp/appiclient_key_crm.pem";
                $arr['spbill_create_ip'] = $scf_data['ip'];
            } else {
                $certAddress = $_SERVER['DOCUMENT_ROOT'] . '/key/apiclient_cert.pem';
                $keyAddress = $_SERVER['DOCUMENT_ROOT'] . '/key/apiclient_key.pem';
                $arr['spbill_create_ip'] = $_SERVER['SERVER_ADDR'];
                if(strpos($_SERVER['SERVER_NAME'], "crmweb.netbcloud.com") !== false){
                    return ["code" => 1, "msg" => "测试站不允许提现"];
                }
            }
            file_put_contents($certAddress, $config['member_apiclient_cert']);
            file_put_contents($keyAddress, $config['member_apiclient_key']);
            $arr['act_name'] = '售后提成';
            $arr['sign'] = $this->makeSign($arr, ['column' => 'key', 'value' => $config['qy_mch_key']]);//此处value填写商户号的API密钥
            $url = 'https://api.mch.weixin.qq.com/mmpaymkttransfers/promotion/paywwsptrans2pocket';
            $xmlData = Tools::arrayToXml($arr);
            $res = Tools::xmlToArray($this->postXmlCurl($xmlData, $url, [$certAddress, $keyAddress]));
            if ($res['return_code'] == 'SUCCESS' && $res['result_code'] == 'SUCCESS') {
                $i_data['pay_number'] = $res['payment_no'];
                $i_data['pay_time'] = $res['payment_time'];
                $withdrawalModel = new Withdrawal();
                $fields = ['column' => 'id', 'value' => $data['id']];
                $withdrawalModel->takeMoneyUpdate($fields, $i_data);
                return true;
            } else {
                Log::info("企业微信转账失败结果：" . var_export($res, 1));
                return ["code" => 1, "msg" => $this->getCode($res["err_code"]) ?: "{$res["return_msg"]},{$res["err_code_des"]}"];
            }
        }catch (\Exception $e){
            return ["code" => 1, "msg" => $e->getMessage()];
        }
    }

    public function getCode($code){
        $msg = [
            "AMOUNT_LIMIT" => "每次付款金额必须大于1元",
            "OPENID_ERROR" => "请核对商户自身公众号appid和用户在此公众号下的openid",
            "NOTENOUGH" => "帐号余额不足", "CA_ERROR" => "请求没带证书或者带上了错误的证书",
            "V2_ACCOUNT_SIMPLE_BAN" => "用户微信支付账户未知名，无法付款",
            "SENDNUM_LIMIT" => "	用户今日付款次数超过限制",
            "PARAM_ERROR" => "参数缺失，或参数格式出错，参数不合法等"
        ];
        return isset($msg[$code]) ? $msg[$code] : "";
    }

    /* post传输xml格式curl函数 */
    public static function postXmlCurl($xml, $url, $pem = [])
    {
        $header[] = "Content-type: text/xml";
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,FALSE);
        curl_setopt($ch,CURLOPT_SSL_VERIFYHOST,FALSE);//严格校验
        curl_setopt($ch, CURLOPT_SSLCERT, $pem[0]);
        curl_setopt($ch, CURLOPT_SSLKEY,$pem[1]);
        // post数据
        curl_setopt($ch, CURLOPT_POST, 1);
        // post的变量
        curl_setopt($ch, CURLOPT_POSTFIELDS, $xml);
        $data = curl_exec($ch);
        //返回结果
        if ($data) {
            curl_close($ch);
            return $data;
        }else{
            $error = curl_errno($ch);
            curl_close($ch);
            return "curl出错，错误码:$error";
        }
    }

    /* 生成签名 */
    public function makeSign($fields,$extend)
    {
        //签名步骤一：按字典序排序参数
        ksort($fields);
        $sign = '';
        foreach ($fields as $key => $value) {
            $sign .= $key . '=' . $value . '&';
        }
        $sign_str = '';
        if (strlen($sign) > 0) {
            $sign_str = substr($sign, 0, strlen($sign) - 1);
        }
        //签名步骤二：在string后加入secret
        $sign_str = $sign_str.'&'.$extend['column'].'='.$extend['value'];
        //签名步骤三：MD5加密
        $sign_str = md5($sign_str);
        //签名步骤四：所有字符转为大写
        $sign_str = strtoupper($sign_str);
        return $sign_str;
    }
}
